/*
*SopraIM chat handler :
change status
disconnection
swichting to the home page
*/

package sopraim.presenter.servlets;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import sopraim.entity.TextMessage;
import sopraim.presenter.services.UserService;
import sopraim.entity.User;
import sopraim.presenter.services.util.Contact;
import sopraim.presenter.services.util.Utils;

@WebServlet(name="ChatSerlet",
        urlPatterns= {
            "/status",
            "/allStatus",
            "/disconnect",
            "/chat",
            "/home",
            "/addContact",
            "/removeContact",
            "/contact",
            "/searchContact",
            "/acceptContact",
            "/getFriends",
            "/sendTextMessage",
            "/receiveNewTextMessages",
            "/readMessage",
            "/getContactRequests",
            "/getAllContactRequests",
            "/changePassword",
            "/getUserDetails",
        })
public class ChatServlet extends HttpServlet {
    
    private static final String PARAM_SEARCH_CONTACT = "username";
    private static final String PARAM_CONTACT_ID = "contact";
    private static final String PARAM_ACCEPT_CONTACT = "accept";
    private static final String PARAM_MESSAGE_ID = "messageID";
    private static final String PARAM_MESSAGE = "message";
    private static final String ATT_SEARCH_CONTACT_RES = "contacts";
    private static final String ATT_TEXT_MESSAGE = "message";
    private static final String ATT_ERROR = "error";
    private static final String ATT_TYPE = "type";
    private static final String ATT_NOTIF = "notification";
    private static final String ATT_TEXT_MESSAGES_RECEIVED = "receivedMessages";
    private static final String CHAMP_PASS = "password";
    private static final String CHAMP_NEWPASS = "newPwd";
    private static final String CHAMP_CONF = "confirm";
    
    UserService userService = new UserService();
    Utils utils = new Utils();
    
    /**
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code>
     * methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        HttpSession session = request.getSession();
        String userPath = request.getServletPath();
        User localUser = (User)(session.getAttribute(ConnectionServlet.ATT_USER));
        PrintWriter out = response.getWriter();
        //forward home page
        HashMap<String,String> errors = new HashMap();
        int contactId;
        long messageId;
        switch (userPath) {
            case "/home":
                userPath="/Home";
                break;
            case "/chat":
                userPath="/Chat";
                break;
            case "/status":
                String notif;
                try {
                    String status = request.getParameter("status");
                    userService.setUserStatus(localUser, status);
                    notif="successful";
                    System.out.println("status changed");
                } catch (Exception ex) {
                    notif=ex.getMessage();
                    System.out.println(ex.getMessage());
                }
                response.setContentType("text/html;charset=UTF-8");
                response.getWriter().print(notif);
                return;
            case "/disconnect":
                try {
                    userService.disconnect(localUser.getUsername());
                } catch (Exception ex) {
                    Logger.getLogger(ChatServlet.class.getName()).log(Level.SEVERE, null, ex);
                }
                session.invalidate();
                response.sendRedirect("index.html");
                return;
            case "/searchContact":
                userPath="/manageUser/addContact";
                String contactName= request.getParameter(PARAM_SEARCH_CONTACT).toString();
                try {
                    ArrayList<Contact> res = userService.searchContact(localUser, contactName);
                    request.setAttribute(ATT_SEARCH_CONTACT_RES, res);
                    
                } catch (Exception ex) {
                    errors.put(PARAM_SEARCH_CONTACT, ex.getMessage());
                    request.setAttribute(ATT_ERROR, errors);
                }
                break;
            case "/addContact":
                userPath="/manageUser/addContact";
                contactId = Integer.parseInt(request.getParameter(PARAM_CONTACT_ID).toString());
                try {
                    userService.addContact(localUser, contactId);
                } catch (Exception ex) {
                    errors.put(PARAM_CONTACT_ID, ex.getMessage());
                    request.setAttribute(ATT_ERROR, errors);
                    response.getWriter().write(ex.getMessage()+":"+contactId); return;
                }
                break;
            case "/removeContact":
                userPath="/manageUser/addContact";
                contactId = Integer.parseInt(request.getParameter(PARAM_CONTACT_ID).toString());
                try {
                    userService.removeContact(localUser, contactId);
                } catch (Exception ex) {
                    errors.put(PARAM_CONTACT_ID, ex.getMessage());
                    request.setAttribute(ATT_ERROR, errors);
                    response.getWriter().write(ex.getMessage()+":"+contactId);
                }
                break;
            case "/acceptContact":
                response.sendRedirect("home");
                contactId = Integer.parseInt(request.getParameter(PARAM_CONTACT_ID).toString());
                boolean accept = Boolean.parseBoolean(request.getParameter(PARAM_ACCEPT_CONTACT).toString());
                
                try {
                    userService.acceptContact(localUser, contactId, accept);
                    request.setAttribute(ATT_NOTIF, "Contact "+(accept?"accepted":"refused"));
                    System.out.println(ATT_NOTIF);
                } catch (Exception ex) {
                    errors.put(PARAM_CONTACT_ID, ex.getMessage());
                    request.setAttribute(ATT_ERROR, errors);
                    System.out.println(errors);
                }
                
                return;
            case "/sendTextMessage":
                //TODO: userPath="/manageUser/acceptContact";
                contactId = Integer.parseInt(request.getParameter(PARAM_CONTACT_ID).toString());
                String message = request.getParameter(PARAM_MESSAGE).toString();
                System.err.println("message received:"+message);
                try {
                    userService.sendTextMessage(localUser, contactId, message);
                    request.setAttribute(ATT_TEXT_MESSAGE, message);
                } catch (Exception ex) {
                    errors.put(ConnectionServlet.ATT_USER, ex.getMessage());
                    request.setAttribute(ATT_ERROR, errors);
                }
                userPath="/Home";
                break;
            case "/receiveNewTextMessages":
                //TODO: userPath="/manageUser/acceptContact";
                try {
                    ArrayList<TextMessage>messages = userService.receiveNewTextMessages(localUser);
                    request.setAttribute(ATT_TEXT_MESSAGES_RECEIVED, messages);
                    out.print(utils.messageToJson(messages));
                    out.flush();
                    out.close();
                    return;
                } catch (Exception ex) {
                    errors.put(ConnectionServlet.ATT_USER, ex.getMessage());
                    request.setAttribute(ATT_ERROR, errors);
                    System.err.println("Error : "+ex.getMessage());
                }
                break;/*
                case "/receiveMessage":
                //TODO: userPath="/manageUser/acceptContact";
                localUserId = Integer.parseInt(session.getAttribute(ConnectionServlet.ATT_USER).toString());
                messageId = Long.parseLong(request.getParameter(PARAM_MESSAGE_ID).toString());
                try {
                userService.receiveMessage(localUserId, messageId);
                } catch (Exception ex) {
                errors.put(PARAM_MESSAGE_ID, ex.getMessage());
                request.setAttribute(ATT_ERROR, errors);
                }
                break;*/
            case "/readMessage":
                //TODO: userPath="/manageUser/acceptContact";
                messageId = Long.parseLong(request.getParameter(PARAM_MESSAGE_ID).toString());
                try {
                    userService.readMessage(localUser, messageId);
                } catch (Exception ex) {
                    errors.put(PARAM_MESSAGE_ID, ex.getMessage());
                    request.setAttribute(ATT_ERROR, errors);
                }
                break;
            case "/contact":
                TODO: userPath="/manageUser/Contact";
                break;
            case "/getFriends":
                PrintWriter w= response.getWriter();
                try{
                    ArrayList<User> a = userService.getFriends(localUser);
                    w.print( utils.toJson(a).toString());
                }
                catch(Exception e){
                    
                    JsonObject o = Json.createObjectBuilder().add("error", true).build();
                    w.print(o.toString());
                }
                w.flush();
                w.close();
                return;
                
            case "/getContactRequests":
                try{
                    ArrayList<User> a = userService.getContactRequest(localUser);
                    out.print( utils.toJson(a));
                }
                catch(Exception e){
                    
                    JsonObject o = Json.createObjectBuilder().add("error", true).build();
                    out.print(o.toString());
                }
                out.flush();
                out.close();
                return;
                //get the user friends requests
            case "/getAllContactRequests":
                PrintWriter writer= response.getWriter();
                ArrayList<User> req;
                try{
                    req = userService.getNotAnsweredContactRequests(localUser);
                    writer.print(utils.toJson(req));
                }
                catch(Exception e){
                    
                    JsonObject o = Json.createObjectBuilder().add("error", true).build();
                    //writer.print(o.toString());
                    writer.print(o.toString());;
                }
                writer.flush();
                writer.close();
                return;
            case "/changePassword":
                String password = request.getParameter(CHAMP_PASS);
                String confirm = request.getParameter(CHAMP_CONF);
                String newPwd = request.getParameter(CHAMP_NEWPASS);
                boolean error = false;
                try{
                    userService.changePassword(localUser, password, newPwd);
                }
                catch(Exception e){
                    error = true;
                }
                JsonObject obj = Json.createObjectBuilder()
                        .add("error", error)
                        .build();
                PrintWriter resp = response.getWriter();
                resp.print(obj.toString());
                resp.flush();
                resp.close();
                return;
            case "/allStatus":
                JsonArrayBuilder array = Json.createArrayBuilder();
                ArrayList<String> allstatus = userService.getAllStatus();
                try {
                    String currentStatus = userService.getUserStatus(localUser);
                    for(String s : allstatus){
                        boolean isSelected = currentStatus.equals(s)?true:false;
                        JsonObject json =Json.createObjectBuilder()
                                .add("value", s)
                                .add("imageSrc", "inc/img/"+s+".png")
                                .add("selected",isSelected)
                                .build();
                        array.add(json);
                        
                    }
                    System.out.println(currentStatus);
                    out.print(array.build());
                    out.flush();
                    out.close();
                    return;
                } catch (Exception ex) {
                    Logger.getLogger(ChatServlet.class.getName()).log(Level.SEVERE, null, ex);
                    userPath = "/Home";
                    System.out.println("curr stat : "+ex.getMessage());
                }
                break;
            case "/getUserDetails":
                out.print(utils.toJson(localUser));
                out.flush();
                out.close();
                return;
        }
        
        String page ="/WEB-INF"+userPath+".jsp";
        request.getRequestDispatcher(page).forward(request, response);
        
    }
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
    
    /**
     * Handles the HTTP <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
    
    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
    
}
